package org.javacore.concurrent;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 * User: Fan
 * Date: 2019/9/15
 * Time: 16:19
 * Description: Semaphore实现按顺序打印
 */
public class SemaphoreA {
    // 线程池
    private final static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
            .setNameFormat("demo-pool-%d").build();
    private final static ExecutorService service = new ThreadPoolExecutor(5, 200,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
    public static void main(String[] args) {
        SemaphoreA.Foo f = new SemaphoreA.Foo();
        service.execute(() -> {
            f.first(()->{
                System.out.println(1);
            });
        });
        service.execute(() -> {
            try {
                f.second(()->{
                    System.out.println(2);
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        service.execute(() -> {
            try {
                f.third(()->{
                    System.out.println(3);
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        service.shutdown();
    }
    public static class Foo {
        private Semaphore semaphoreA;
        private Semaphore  semaphoreB;

        public Foo() {
            semaphoreA = new Semaphore(0);
            semaphoreB = new Semaphore(0);
        }

        public void first(Runnable printFirst){
            printFirst.run();
            semaphoreA.release();
        }

        public void second(Runnable printSecond) throws InterruptedException {
            semaphoreA.acquire();
            printSecond.run();
            semaphoreB.release();
        }

        public void third(Runnable printThird) throws InterruptedException {
            semaphoreB.acquire();
            printThird.run();
        }
    }

}
